package com.gzdh.tang.config.leshua.leshuaUtil;

import com.gzdh.tang.config.leshua.leshuaUtil.exception.BizConstants;
import com.gzdh.tang.config.leshua.leshuaUtil.exception.BizRuntimeException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author eden
 * @date 2018/5/21 下午3:36
 * @desc
 */
public class LeshuaConstants {
	//版本号
	public static final String VERSION_INITIAL = "1.0";
	//编码类型
	public static final String CHARSET = "UTF-8";
	//返回成功码
	public static final String RESP_CODE = "000000";
	//产品类型
	public static final String OPEN_TYPE = "1";
	//费率进制
	public static final Integer RATE_HEX = 10000;
	
	public static final String MCC_CODE = "1520";
	
	public static final String MCC_Type = "5";
	
	public static final String RESTAURANT_MCC_CODE = "5813";
	
	public static final String RESTAURANT_MCC_Type = "1";

	/**
	 * @author eden
	 * @date 2018/5/21 下午3:36
	 * @desc
	 */
	public static class HttpClientHelper {

		private static Logger log = LoggerFactory.getLogger(HttpClientHelper.class);

		public static final String ACCEPT_TYPE_JSON = "application/json";
		public static final String ACCEPT_TYPE_HTML = "text/html";
		public static final String ACCEPT_TYPE_XML = "application/xml";
		public static final String ACCEPT_TYPE_X_WWW = "application/x-www-form-urlencoded";
		public static final int DEFAULT_SO_TIMEOUT = 30000;
		public static final int DEFAULT_CONN_TIMEOUT = 6000;
		public static final int DEFAULT_CONN_REQ_TIMEOUT = 5000;

		private static PoolingHttpClientConnectionManager cm;

		private RequestConfig requestConfig;

		static {
			cm = new PoolingHttpClientConnectionManager();
			cm.setMaxTotal(10000);
			cm.setDefaultMaxPerRoute(500);
		}

		@PostConstruct
		public void init() {
			// 设置默认http状态参数
			requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SO_TIMEOUT).setConnectTimeout(DEFAULT_CONN_TIMEOUT)
					.setConnectionRequestTimeout(DEFAULT_CONN_REQ_TIMEOUT).build();
		}

		/**
		 * 关闭HttpClient连接池
		 */
		@PreDestroy
		public void destory() {
			if (cm != null) {
				log.info("关闭HttpClient线程池");
				cm.shutdown();
			}
		}

		/**
		 * get请求默认格式为html，编码为utf-8
		 * @param url
		 * @return
		 */
		public String get(String url) {
			return this.get(url, "text/html", null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * get请求,指定格式，编码为utf-8
		 * @param url
		 * @param acceptType
		 * @return
		 */
		public String get(String url, String acceptType) {
			return this.get(url, acceptType, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * get请求,指定格式，编码为utf-8
		 * @param url
		 * @param acceptType
		 * @return
		 */
		public String get(String url, Map<String, String> params, String acceptType) {
			StringBuilder paramSB = new StringBuilder();
			if(params != null){
				for (Map.Entry<String, String> entry : params.entrySet()) {
					paramSB.append("&").append(entry.getKey()).append("=").append(entry.getValue());
				}
			}
			if (paramSB.length() > 0) {
				url = url + "?" + paramSB.substring(1);
			}
			return this.get(url, acceptType);
		}

		/**
		 * get请求,指定格式，编码为utf-8，需要授权
		 * @param url
		 * @param acceptType
		 * @return
		 */
		public String get(String url, String acceptType, String auth) {
			return this.get(url, acceptType, auth, BizConstants.CHARSET_UTF8);
		}

		/**
		 * get请求,指定格式，指定编码，需要授权
		 * @param url
		 * @param acceptType
		 * @return
		 */
		public String get(String url, String acceptType, String auth, String charset) {
			String result = null;
			CloseableHttpClient httpClient = null;
			CloseableHttpResponse response = null;
			HttpEntity entity = null;
			try {
				httpClient = HttpClients.custom().setConnectionManager(cm).setConnectionManagerShared(true).build();
				HttpGet httpGet = new HttpGet(url);
				httpGet.setConfig(requestConfig);
				httpGet.setHeader("Accept", acceptType);
				httpGet.setHeader("Content-Type", acceptType + ";charset=" + charset);
				if (auth != null) {
					httpGet.setHeader("Authorization", auth);
				}
				// 执行客户端请求
				response = httpClient.execute(httpGet);
				entity = response.getEntity();
				if (entity != null) {
					result = EntityUtils.toString(entity, charset);
				}
			} catch (Exception e) {
				throw new BizRuntimeException(null, e);
			} finally {
				// 关闭连接
				if (entity != null) {
					EntityUtils.consumeQuietly(entity);
				}
				if (response != null) {
					try {
						response.close();
					} catch (IOException e) {
						log.error("关闭HttpResponse出错，错误信息：" + e.getMessage(), e);
					}
				}
				if (httpClient != null) {
					try {
						httpClient.close();
					} catch (IOException e) {
						log.error("关闭HttpClient出错，错误信息：" + e.getMessage(), e);
					}
				}
			}
			return result;
		}

		/**
		 * post请求，默认utf-8编码，期望接收text/html
		 * @param url
		 * @param params
		 * @return
		 */
		public String post(String url, String params) {
			return this.post(url, params, ACCEPT_TYPE_HTML, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，默认utf-8编码，指定格式
		 * @param url
		 * @param params
		 * @param acceptType
		 * @return
		 */
		public String post(String url, String params, String acceptType) {
			return this.post(url, params, acceptType, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，默认utf-8编码，指定格式
		 * @param url
		 * @param params
		 * @param acceptType
		 * @return
		 */
		public String post(String url, String params, String acceptType, int socketTimeOut , int connectTimeOut) {
			requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeOut).setConnectTimeout(connectTimeOut)
					.setConnectionRequestTimeout(DEFAULT_CONN_REQ_TIMEOUT).build();
			return this.post(url, params, acceptType, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，默认utf-8编码，指定格式，需要授权
		 * @param url
		 * @param params
		 * @param acceptType
		 * @param auth
		 * @return
		 */
		public String post(String url, String params, String acceptType, String auth) {
			return this.post(url, params, acceptType, auth, BizConstants.CHARSET_UTF8);
		}

		/**
		 *  post请求，指定编码，指定格式，需要授权
		 * @param url
		 * @param params
		 * @param acceptType
		 * @param auth
		 * @param charset
		 * @return
		 */
		public String post(String url, String params, String acceptType, String auth, String charset) {
			String result = null;
			CloseableHttpClient httpClient = null;
			CloseableHttpResponse response = null;
			HttpEntity entity = null;
			try {
				httpClient = HttpClients.custom().setConnectionManager(cm).setConnectionManagerShared(true).build();
				HttpPost httpPost = new HttpPost(url);
				httpPost.setConfig(requestConfig);
				httpPost.setHeader("Accept", acceptType);
				httpPost.setHeader("Content-Type", acceptType + ";charset=" + charset);
				if (auth != null) {
					httpPost.setHeader("Authorization", auth);
				}
				BasicHttpEntity requestBody = new BasicHttpEntity();
				byte[] content = params.getBytes(charset);
				requestBody.setContent(new ByteArrayInputStream(content));
				requestBody.setContentLength(content.length);
				httpPost.setEntity(requestBody);
				if (StringUtils.startsWithIgnoreCase(url, "https")) {
					trustAllHosts();
				}
				// 执行客户端请求
				response = httpClient.execute(httpPost);
				entity = response.getEntity();
				if (entity != null) {
					result = EntityUtils.toString(entity, charset);
				}
			} catch (Exception e) {
				throw new BizRuntimeException(null, e);
			} finally {
				// 关闭连接
				if (entity != null) {
					EntityUtils.consumeQuietly(entity);
				}
				if (response != null) {
					try {
						response.close();
					} catch (IOException e) {
						log.error("关闭HttpResponse出错，错误信息：" + e.getMessage(), e);
					}
				}
				if (httpClient != null) {
					try {
						httpClient.close();
					} catch (IOException e) {
						log.error("关闭HttpClient出错，错误信息：" + e.getMessage(), e);
					}
				}
			}
			return result;
		}

		/**
		 * post请求，默认utf-8编码，期望接收text/html
		 * @param url
		 * @param formParams
		 * @return
		 */
		public String postForm(String url, Map<String, String> formParams) {
			return this.postForm(url, formParams, ACCEPT_TYPE_HTML, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，默认utf-8编码，期望接收text/html
		 * @param url
		 * @param formParams
		 * @param socketTimeOut
		 * @param connectTimeOut
		 * @return
		 */
		public String postForm(String url, Map<String, String> formParams, int socketTimeOut , int connectTimeOut) {
			requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeOut).setConnectTimeout(connectTimeOut)
					.setConnectionRequestTimeout(DEFAULT_CONN_REQ_TIMEOUT).build();
			return this.postForm(url, formParams, ACCEPT_TYPE_HTML, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，默认utf-8编码，指定格式
		 * @param url
		 * @param formParams
		 * @param acceptType
		 * @return
		 */
		public String postForm(String url, Map<String, String> formParams, String acceptType) {
			return this.postForm(url, formParams, acceptType, null, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，默认utf-8编码，指定格式，需要授权
		 * @param url
		 * @param formParams
		 * @param acceptType
		 * @param auth
		 * @return
		 */
		public String postForm(String url, Map<String, String> formParams, String acceptType, String auth) {
			return this.postForm(url, formParams, acceptType, auth, BizConstants.CHARSET_UTF8);
		}

		/**
		 * post请求，指定编码，指定格式，需要授权
		 * @param url
		 * @param formParams
		 * @param acceptType
		 * @param auth
		 * @param charset
		 * @return
		 */
		public String postForm(String url, Map<String, String> formParams, String acceptType, String auth, String charset) {
			List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
			if (formParams != null) {
				for (Map.Entry<String, String> entry : formParams.entrySet()) {
					urlParameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
			}
			boolean isSucc = false;
			HttpEntity requestEntity = null;
			try {
				requestEntity = new UrlEncodedFormEntity(urlParameters, charset);
				isSucc = true;
			} catch (UnsupportedEncodingException e) {
				log.error(e.getMessage(), e);
			}
			return isSucc ? this.postForm(url, requestEntity, acceptType, auth, charset) : null;
		}

		/**
		 * Trust every server - dont check for any certificate
		 */
		public static void trustAllHosts() {
			// Create a trust manager that does not validate certificate chains
			TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
				public X509Certificate[] getAcceptedIssuers() {
					return new X509Certificate[] {};
				}

				public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				}
			} };

			try {
				SSLContext sc = SSLContext.getInstance("TLS");
				sc.init(null, trustAllCerts, new java.security.SecureRandom());
				HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}

		/**
		 * post请求，指定编码，指定格式，需要授权
		 * @param url
		 * @param requestEntity
		 * @param acceptType
		 * @param auth
		 * @param charset
		 * @return
		 */
		private String postForm(String url, HttpEntity requestEntity, String acceptType, String auth, String charset) {
			String result = null;
			CloseableHttpClient httpClient = null;
			CloseableHttpResponse response = null;
			HttpEntity entity = null;
			try {
				httpClient = HttpClients.custom().setConnectionManager(cm).setConnectionManagerShared(true).build();
				HttpPost httpPost = new HttpPost(url);
				httpPost.setConfig(requestConfig);
				httpPost.setHeader("Accept", acceptType);
				httpPost.setHeader("Content-Type","application/x-www-form-urlencoded;charset=" + charset);
				if (auth != null) {
					httpPost.setHeader("Authorization", auth);
				}
				httpPost.setEntity(requestEntity);
				if (StringUtils.startsWithIgnoreCase(url, "https")) {
					trustAllHosts();
				}
				// 执行客户端请求
				response = httpClient.execute(httpPost);
				entity = response.getEntity();
				if (entity != null) {
					result = EntityUtils.toString(entity, charset);
				}
			} catch (Exception e) {
				throw new BizRuntimeException(null, e);
			} finally {
				// 关闭连接
				if (entity != null) {
					EntityUtils.consumeQuietly(entity);
				}
				if (response != null) {
					try {
						response.close();
					} catch (IOException e) {
						log.error("关闭HttpResponse出错，错误信息：" + e.getMessage(), e);
					}
				}
				if (httpClient != null) {
					try {
						httpClient.close();
					} catch (IOException e) {
						log.error("关闭HttpClient出错，错误信息：" + e.getMessage(), e);
					}
				}
			}
			return result;
		}

		/**
		 *
		 * @param url
		 * @param acceptType
		 * @param paramMap
		 * @param fileMap
		 * @param charset
		 * @return
		 */
		public String postWithMultipartEntity(String url, String acceptType, Map<String, String> paramMap, Map<String, File> fileMap,
				String charset) {
			String result = null;
			CloseableHttpClient httpClient = null;
			CloseableHttpResponse response = null;
			HttpEntity entity = null;
			try {
				httpClient = HttpClients.custom().setConnectionManager(cm).setConnectionManagerShared(true).build();
				HttpPost httpPost = new HttpPost(url);
				httpPost.setConfig(requestConfig);
				httpPost.setHeader("Accept", acceptType);

				MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
				multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
				multipartEntityBuilder.setCharset(Charset.forName(charset));
				// 字符串参数
				if (paramMap != null) {
					for (Map.Entry<String, String> entry : paramMap.entrySet()) {
						StringBody strBody = new StringBody(entry.getValue(), ContentType.APPLICATION_JSON);
						multipartEntityBuilder = multipartEntityBuilder.addPart(entry.getKey(), strBody);
					}
				}
				// 文件参数
				if (fileMap != null) {
					for (Map.Entry<String, File> entry : fileMap.entrySet()) {
						FileBody fileBody = new FileBody(entry.getValue());
						multipartEntityBuilder = multipartEntityBuilder.addPart(entry.getKey(), fileBody);
					}
				}
				HttpEntity reqEntity = multipartEntityBuilder.build();
				httpPost.setEntity(reqEntity);

				if (StringUtils.startsWithIgnoreCase(url, "https")) {
					trustAllHosts();
				}
				// 执行客户端请求
				response = httpClient.execute(httpPost);
				entity = response.getEntity();
				if (entity != null) {
					result = EntityUtils.toString(entity, charset);
				}
			} catch (Exception e) {
				throw new BizRuntimeException(null, e);
			} finally {
				// 关闭连接
				if (entity != null) {
					EntityUtils.consumeQuietly(entity);
				}
				if (response != null) {
					try {
						response.close();
					} catch (IOException e) {
						log.error("关闭HttpResponse出错，错误信息：" + e.getMessage(), e);
					}
				}
				if (httpClient != null) {
					try {
						httpClient.close();
					} catch (IOException e) {
						log.error("关闭HttpClient出错，错误信息：" + e.getMessage(), e);
					}
				}
			}
			return result;
		}

	}
}
